﻿﻿/***************************  Ccay IGrid Operation  ***********************************/
(function(IGrid,Const){
	var operationMsg = Const.I18n.operation = {
		selectMsg: "ccay.common.message.selectedRecords",
		confirmMsg: "ccay.common.message.confdel",
		noSelectMsg: "ccay.common.message.selectedRecords",
		clearCacheMsg: "ccay.common.message.clearCache",
		successMsg: "ccay.common.message.success"
	};
	
	/** 注册操作插件 */
	Ccay.UI.XControl.addPlugin("XGrid", "operation", {
	    build: function (grid, op) 
	    {
	    	if (op.operation) {
	    		//初始化删除和插入缓存
	    		$.each(op.operation, function (name, optOp){
	    			IGrid.Operation.bind(grid, op, name, optOp);
	    		});
	    		// 加载时显示新增行
	    		if (!op._reIniting && op.showNewRow && op.operation.insert) {
	    			op.handler.complete.add(function (grid, op) {
	    				IGrid.Operation.get("insert").operate(grid, op, op.operation.insert);
	    			});
	    		}
	    	}
	    },
	    clear: function (grid, op) {
	    	if (op.operation) {
		    	$.each(op.operation, function (name, optOp){
		    			IGrid.Operation.clear(grid, op, optOp);
		    	});
	    	}
	    }
	});
	
	Ccay.UI.XControl.extendIManager("XGrid", {
		getInsertedRecords: function (fields, fnFilter) 
		{
			return this.op.Storage.getInsertedRecords(fields, fnFilter);
		},
		getDeletedRecords: function (fields, fnFilter)
		{
	    	return this.op.Storage.getDeletedRecords(fields, fnFilter);
		},
		getErrorRecords: function () {
			// 有缓存时取缓存数据
			var filterFn = function(item){
					return item._errorNo ? true : false;
				};
			return this.op._cache ? this.getInsertedRecords(filterFn) : this.op.Storage.filter(filterFn);
		},
		/** @description 追加行
		 * 	@param records {Array} 需追加的数据集
		 *  @param setting {Object} 追加位置设置信息
		 */
		appendRow: function (records, setting) {
			this.op.operation || (this.op.operation = {});
			this.op.operation.insert || (this.op.operation.insert = {});
			var grid = this, focusRow = grid.getFocusRow(), customSetting, record,
				defaultRow = grid.op.operation.insert.defaultRow && grid.op.operation.insert.defaultRow.data;
        	$.each(records, function (i, item) {
        		record = defaultRow ? $.extend(true, {}, defaultRow, item) : $.extend(true, {}, item);
        		customSetting = setting || (focusRow.length ? {posTr: focusRow} : {});
        		gridInsert.insert(grid, grid.op, record, customSetting, true);
        	});
        },
        /** @description 保存
		 * 	@param ajax {Object} 保存请求配置
		 *  @param isShowMsg {Boolean} 是否显示默认的提示信息
		 */
		save: function (ajax, isShowMsg) {
			var grid = this,
				fnSuccess = ajax.success;
				fnError = ajax.error;
			// 执行成功
			ajax.success = function (result) {
				if (!fnSuccess || fnSuccess(result) !== false) {
					isShowMsg && Ccay.UI.topBox(operationMsg.successMsg);
					ajax.data = null;
					//清空缓存的数据
					grid.clearCache();
					grid.reload("operation", true);
				}
			};
			// 执行失败，提示服务器端验证失败错误信息
			ajax.error = function (textStatus, errorThrown, responseText, status) {
				if ((!fnError || fnError(textStatus, errorThrown, responseText, status) == false) && responseText && responseText.substring(0,1) == "{" ) {
					var fault =  Ccay.DataHelper.toJson(responseText);
					// 判断是否是服务器端验证错误
		       		if(fault != null && fault.code === "ccay.validator.00010001"){
			       		var validErrors = Ccay.DataHelper.toJson(fault.message);
			       		// 后台校验错误处理 l00195395
			       		if (validErrors.fieldErrors && grid.op.showStatus) {
			       			gridSave.checkErrorMsg(grid, validErrors.fieldErrors);
			       			// 更新错误状态
			       			grid.updateStatus("error");
			       			// 弹出
			       			if(grid.op.popupStatus){
			       				grid.popupStatus("error");
			       			}
			       		}
			       		return true;
		       		}else{
		       			// 非ccay.validator.00010001错误是，更新错误状态
		       			grid.op.showStatus && grid.updateStatus("error");
		       		}
				}
			};
			Ccay.doPut(ajax);
		},
		/** @description 删除单行数据
		 * 	@param dataOrTr {Object} 单条数据或单行
		 *  @param isCustomDelete {Boolean/String/Function} 是否自定义删除
		 */
		deleteRow: function (dataOrTr, isCustomDelete) {
			this.endEdit();
			var op = this.op,
				storage = op.Storage,
				// 判断是数据还是行对象
				isData = $.isPlainObject(dataOrTr) ? true : false,
				// 不是数据，则转换成数据
				data = isData ? dataOrTr : this.getRowData(dataOrTr),
				// 获取数据索引
				dataIndex = data._newIndex || data._index,
				// 不是行对象，则转换成行对象
				row = isData ? this.getRow(dataIndex) : dataOrTr,
				isReload;
			// 判断新增数据
			if (data._inserted) {
				// 若是新增数据，则直接删除；否则，将在数据集中删除
				if (dataIndex < 0) {
					storage.insertStorage.destroyItem(dataIndex, row);
					//修复删除新增行之后全选不上 by twx305111 2016年1月14日
					this.op._prevSelCount -=row.length;
				} else {
					// 若是缓存情况，则需清除缓存
					op._cache && storage.Cache.insertCache.cache(data, true, dataIndex);
					isReload = true;
				}
			} else {
				// 自定义删除
				if (isCustomDelete) {
					if (typeof(isCustomDelete) == "function") {
						isCustomDelete(data, row, this);
					} else if (isCustomDelete == "remove") {
						isReload = true;
					}
				} else {
					GridDelete.sendDeleteRequest(this, data);
				}
			}
			// 删除tr后重新加载
			if (isReload) {
				storage.destroyItem(dataIndex);
				op._loadType = "noScroll";
				this.reload(null, null, true);
			}else{
				if(!this.getAllRecords().length){
					this.getHeadTable().find(".igrid-head tr").removeClass("igrid-selected");
					this.getHeadTable().find(".igrid-head .grid-select").addClass("grid-selected-disabled");
				} 
			}
		},
		/** @description 删除批量数据
		 * 	@param dataOrTr {Object} 数组或者行数组
		 *  @param isCustomDelete {Boolean/String/Function} 是否自定义删除
		 */
		deleteRows: function (dataOrTr, isCustomDelete){
			this.endEdit();
			var grid = this, op = this.op, storage = op.Storage,
				// 判断是数据还是行对象
				isData = $.isPlainObject(dataOrTr[0]) ? true : false,
				noInsertedRecords = [], data, row, isHasNew, isReload;
			$.each(dataOrTr, function (i, item) {
				// 不是行对象，则转换成行对象
				row = isData ? false : $(item);
				// 不是数据，则转换成数据
				data = isData ? item : grid.getRowData(row);
				// 删除新增数据
				if (GridDelete.delInsertRow(grid, storage, data, row)) {
					isHasNew = true;
				}
				// 保存非新增数据
				!data._inserted && noInsertedRecords.push(data);
			});
			// 自定义删除
			if (isCustomDelete) {
				if (typeof(isCustomDelete) == "function") {
					isCustomDelete(dataOrTr, grid);
				} else if (isCustomDelete == "remove") {
					isReload = true;
				}
			} else {
				// 存在非新增数据，则发送请求删除，否则删除新增数据
				if (noInsertedRecords.length > 0) {
					GridDelete.sendDeleteRequest(grid, noInsertedRecords);
				} else {
					isReload = true;
				}
			}
			// 删除tr后重新加载
			if (isReload && isHasNew) {
				storage.destroy(function(item){
					return item ? item._destroy : this.ReturnValue.complete;
				});
				op._loadType = "noScroll";
				grid.reload(null, null, true);
			}else{
				if(!grid.getAllRecords().length){
					//修复新增数据未清除全选状态
					grid.getHeadTable().find(".igrid-head tr").removeClass("igrid-selected");
					grid.getHeadTable().find(".igrid-head .grid-select").addClass("grid-selected-disabled");
				} 
			}
		}
	});
	
	/** 操作对象适配器 */
	IGrid.Operation = $.IAdapter({
		bind: function (grid, op, optOp)
		{
			if(optOp.btn)
			{
				var operate = this.operate;
				$(optOp.btn).unbind("click").click(function (e){
					!op._disabled && operate(grid, op, optOp);
				});
			}
		},
		operate: function (grid, op, optOp) {}
		},
		{
			bind: function (grid, op, name, optOp){
				var operation = this.get(name);
				operation && operation.bind(grid, op, optOp);
			},
			clear: function (grid, op, optOp){
				optOp.btn && $(optOp.btn).unbind("click");
				optOp.undoBtn && $(optOp.undoBtn).unbind("click");
			}
		});
	
	/** 添加查询操作 */
	var searchHelper = {
		setParam:function(op,optOp){
			var param;
			if(optOp.panel)
			{
				var panel = $(optOp.panel);
				if(!panel.valid())
					return false;
				param = panel.jsonData()
			}
			else
				param = {};
			
			if (op.ajax && op.ajax.params != null)
			{ 
				var tempParams = op.ajax.params;
				if (tempParams && typeof tempParams == "function") {
					tempParams = tempParams();
				}
				param = $.extend(true, {}, tempParams, param);
			}
			if(op.ajax)
				op.ajax.data = param;
		}
	};	
		
	IGrid.Operation.add("search", {
		bind:function(grid, op, optOp)
		{
			//如果是搜索筛选模式，不用往下处理
			if(op.showSwitch && op.allowFilter && op.genSearchByFilter){
				return;
			}
			// 判断当前是否是搜索模式，否则隐藏搜索表单
			if ((!op.showSwitch && !op.allowFilter) || op.switchMode == "search") {
				optOp.panel && $(optOp.panel).show();
				this.proxy(this.base.bind, grid, op, optOp);
				// 加载时自动搜索
				optOp.autoSearch!==false && searchHelper.setParam(op, optOp);
			} else {
				if (optOp.panel) {
					$(optOp.panel).ccayReset().hide();
				}
			}
		},
		operate: function (grid, op, optOp)
		{
			if (searchHelper.setParam(op, optOp) !== false) {
				var storage = op.Storage;
				if (storage && storage.cacheData && storage.Cache.count()) {
					Ccay.UI.confirm(operationMsg.clearCacheMsg, function (result) {
						if (result) {
							grid.clearCache();
							grid.reload(true, true, true);
						}
					});
				} else {
					grid.reload(true, true, true);
				}
			}
		}
	});
	
	/** 删除方法对象 */
	var GridDelete = IGrid.Operation.del = {
		//删除
		remove: function (grid, op, optOp, isUndo)
		{
			if(optOp.ajax)
			{
				GridDelete.ajaxDel(grid,op,optOp);
			}
			else
			{
				var isDel, records = grid.getSelectedRecords();
				if (records.length > 0) {
					//是否单独撤销
					if (optOp.undoBtn)
					{
						isDel = isUndo ? false : true;
					}
					var delRows = grid.getSelectRows(false),
						row, record, isHasNew,
						// 获取选中行的表头
						selectedHead = grid.getHeadTable().find("." + Const.selected.css);
					// 存在将选中样式去掉
					(selectedHead.length > 0) && selectedHead.removeClass(Const.selected.css, false);
					for(var i = delRows.length - 1;i > -1;i--)
					{
						row = $(delRows[i]);
						record = grid.getRowData(row);
						if (!optOp.fnBeforeDelete || optOp.fnBeforeDelete.call(grid, record, optOp, row, isDel) !== false) {
							GridDelete.delRow(row, isDel, grid);
						}
					}
				} else {
					Ccay.UI.showMessage(operationMsg.selectMsg, "warn");
				}
			}
		},
		// 行预删除方法
		delRow: function (tr, isDel, grid)
		{
			grid.op.Storage.removeItem(grid.getRowData(tr), isDel, tr);
			if(grid.op._activeEditTr != null && grid.getRowIndex(tr) == grid.op._activeEditTr)
			{
				grid.clearActiveEditor();
			}
		},
		// 删除新增行
		delInsertRow: function (grid, storage, item, row) {
			var itemIndex = item._newIndex || item._index;
			// 若是新增数据，则直接删除；否则，将在数据集中删除
			if (itemIndex < 0) {
				storage.insertStorage.destroyItem(itemIndex, row || grid.getRow(itemIndex));
				//修复删除新增行之后全选不上 by twx305111 2016年1月14日
				grid.op._prevSelCount-=1;
				return false;
			} else {
				item._destroy = true;
				// 若是缓存情况，则需清除缓存
				grid.op._cache && storage.Cache.insertCache.cache(item, true, itemIndex);
				return true;
			}
		},
		initAjax:function(grid, optOp){
			if(!optOp.ajax)
			{
				optOp.ajax = {
					url:optOp.url
					//type:'put'
				};
				delete optOp.url;
			}
			optOp.msg || (optOp.msg = {});
			
			optOp.msg = $.extend({
				confirm: operationMsg.confirmMsg,
				noSelected: operationMsg.noSelectMsg
			}, optOp.msg);
			
			Ccay.UI.ajax.setFnSuccess(optOp.ajax,function(){
				grid.reload("operation", true);
			});
		},
		ajaxDel: function (grid, op, optOp) {
			var records = grid.getSelectedRecords(), noInserted;
			if (records.length > 0) {
				Ccay.UI.confirm(optOp.msg.confirm, function(result) {
					optOp.fnConfirm && optOp.fnConfirm.call(grid, result);
					if (result) {
						(grid.op._activeEditTr != null) && grid.clearActiveEditor();
						grid.deleteRows(records);
					}
				});
			} else {
				Ccay.UI.showMessage(optOp.msg.noSelected, "warn");
			}
		},
		sendDeleteRequest: function (grid, records, optOp) {
			var tempDelOp = optOp || grid.op.operation && grid.op.operation.del;
			if (tempDelOp && tempDelOp.ajax) {
				var ajax = $.extend({}, tempDelOp.ajax);
					ajax.data = records;
				if (!tempDelOp.fnBeforeDelete || tempDelOp.fnBeforeDelete.call(grid, ajax.data, tempDelOp, ajax) !== false) {
					Ccay.doPut(ajax);
				}
			}
		}
	};
	
	/**注册删除操作 */
	IGrid.Operation.add("del", {
		bind: function (grid, op, optOp)
		{
			this.base.bind.call(this, grid, op, optOp);
			if(optOp.ajax || optOp.url)
			{//ajax单独删除模式下
				GridDelete.initAjax(grid,optOp);
			}
			else
			{
				if (optOp.undoBtn)
				{
					$(optOp.undoBtn).click(function (e)
					{
						!op._disabled && GridDelete.remove(grid, op, optOp, 1);
					});
				}
			}
			if (!op._reIniting) {
				//数据仓库中添加删除清空选择的代理方法
	    		op.Storage.Trigger.remove.add(function(item,isDel,tr){
	    			tr && tr.toggleClass(Const.deleted.css, isDel);
	    			this.setItemSelected(item,false,tr);
	    		});
			}
		},
		operate: GridDelete.remove
	});
	
	/** 新增方法对象 */
	var gridInsert = IGrid.Operation.insert = {
		//初始化新增数据仓库
		initInsertStorage:function(storage,op,grid){
			if (!op._reIniting) {
				storage.insertStorage = Ccay.Storage.create({
					//重写根据索引获取item的方法
					at:function(index){
						return this.filter(function(item){
							if(item._newIndex == index)
								return this.ReturnValue.last;
						})[0];
					},
					//重写销毁方法
					destroyItem:function(index,args){
						return this.destroy(function(item){
							if(item._newIndex == index)
								return this.ReturnValue.last;
						},args);
					},
					insertItem:function(item,start,args){
			        	if(item)
			        	{
				            this.setStatus(item,this.Status.inserted);
				            this.dataset.push(item);
				            this.fireTrigger("insert",item,start,args);
			        	}
			            return this;
			        }
				});
				var trigger = storage.insertStorage.Trigger;
				trigger.destroy = storage.Trigger.destroy;
				trigger.insert = storage.Trigger.insert;
				trigger.destroy.add(function(item,tr){
					tr && tr.remove();
				});
			}
			this.setStorage(storage,op,grid);
		},
		setStorage:function(storage,op,grid){
			if (!op._reIniting) {
				//扩展数据仓库
				storage.extend({
					insertItem:function(item,start,args){
						this.insertStorage.insertItem(item,start,args);
						return this;
					},
					at:function(index){
						return index < 0 ? this.insertStorage.at(index) : this.proxy(this.fn.at,index);
					},
					filter:function(fields, fnFilter, copy, fnHandle, includeInserted){
						var records = this.proxy(this.fn.filter, fields, fnFilter, copy, fnHandle);
						if(includeInserted !== false && this.insertStorage && this.insertStorage.len())
							return records.concat(this.insertStorage.getInsertedRecords(fields,fnFilter,true));
						return records;
					},
					sort: function (field, sort, start, end) {
						this.mergeNewData(!op._requesting, op);
						this.proxy(this.fn.sort, field, sort, start, end);
						return this;
					},
				    //新增数据合并
				    mergeNewData:function(merge,op){
						var insertStore = this.insertStorage;
						if(insertStore.len())
						{
							if(merge){
								var addNum = 0,store = this;
								insertStore.sort("_index","asc").each(function(item,i){
									delete item._newIndex;
									delete item._seq;
									//判断是否位置插入数据
									if(item._index)
										store.fn.insertItem.call(store,item,item._index + addNum);
									else
										store.fn.insertItem.call(store,item,0);
									addNum++;
								});
							}
							insertStore.clear();
						}
					},
					clear: function (args) {
						this.dataset = [];
						this.insertStorage.dataset = [];
						this.fireTrigger("clear",args);
					}
				});
			}
			op.handler.beforeBindData.add(function(grid,op){
				grid.op.Storage.mergeNewData(!op._requesting,op);
			});
		},
		//新增
		insert: function (grid, op, data, setting, isAppendRow)
		{
			//var newData = {data: $.extend(true, {}, data.data || data)};
			newData = data.data ? data : {data:data};
			op.operation.insert.trTmpl || (op.operation.insert.trTmpl = "<% var i = index;var _rowNo = - 1; with(data){ %>" + op.tmpl + "<% } %>");
			grid.getBodyPanel().find(".grid-no-result").remove();
			return this.addRow(grid, op.operation.insert,newData, setting, isAppendRow);
		},
		//新增行
		addRow: function(grid, optOp, record, setting, isAppendRow)
		{
			//修复新增数据未清除全选状态
			grid.getHeadTable().find(".igrid-head tr").removeClass("igrid-selected");
			grid.getHeadTable().find(".igrid-head .grid-select").removeClass("grid-selected-disabled");
			var op = grid.op;
			// 缓存新增行数据
			record.data._newIndex = -(++optOp.index);
			// 设置新增行的索引
			record.data._seq = "+" + optOp.index;
			// 缓存数据中，复制新增数据时，去除缓存key
			(record.data._cacheKey != null) && (record.data._cacheKey = null);
			// 数据处理
			setting.dataHandle && setting.dataHandle(record.data,grid);
			
			var tbody = grid.getDataBody(),insertPos,storage = op.Storage;
			
			if (!setting.posTr)
			{
				// 不存在新增定位行时，默认是以第一个不是新增行为定位，否则以光标定位行定位
				var focusRow = grid.getFocusRow(), rowData;
				if (focusRow.length) {
					setting.posTr = focusRow;
					rowData = grid.getRowData(focusRow);
					if(rowData){
						insertPos = rowData._index;
					}else{
						setting.posTr = tbody.children(':not(.igrid-newrow):first');
						insertPos = 0;
					}
				} else {
					setting.posTr = tbody.children(':not(.igrid-newrow):first');
					insertPos = 0;
				}
			}
			else {
				if(setting.posIndex != null)
					insertPos = setting.posIndex;
				else if(!grid.isNewRow(setting.posTr))
					insertPos = grid.getRowIndex(setting.posTr);// + (setting.position == "after" ? 1 : 0);	
				else
					//修复新增数据后删除原有数据顺序错乱的问题
					insertPos = grid.getRowData(setting.posTr)._index;
			}
			
			var pageInf = op.pagerOp.pageInf;
			insertPos += (pageInf.curPage-1) * pageInf.pageSize;
			storage.insertItem(record.data,insertPos);
			var newTr = Ccay.UI.template(optOp.trTmpl, record, null, null, {_grid: grid}, true), top,newTrDom = $(newTr);
			// 新增行全选功能同步
			newTrDom.find(".igrid-multi.grid-select").length > 0 && !op._prevSelCount ? op._prevSelCount=1 : op._prevSelCount++;
			// 给新增的行数据设置rowIdx
			record.data.rowIdx = record.data._newIndex;
			insertPos && (record.data._index = insertPos);
			//是否定位插入
			if (setting.posTr.length) {
				if(setting.position == "after") 
					setting.posTr.after(newTrDom);
				else
					setting.posTr.before(newTrDom);
				//修复行合并下新增问题
				if(op.rowRender && op.rowRender == "rowSpan"){
					var nextRow = newTrDom.next();
					var nextCells = nextRow.children("td[field]:hidden");
					function getPrevRowspanCell(currRow,currField,index){
						index++;
						var prevRow = currRow.prev(),
							prevCell = grid.getCellByField(prevRow.attr("_row")*1,currField);
						if(prevCell.is(":hidden")){
							return getPrevRowspanCell.call(this,prevRow,currField,index);
						}
						return {
							prevCell:prevCell,
							index:index
						};
					};
					nextCells.each(function(){
						var cellCol = grid.getColumnOp($(this)),currPos=getPrevRowspanCell(newTrDom,cellCol.field,0);
						$(this).attr("rowspan",currPos.prevCell.attr("rowspan")*1-currPos.index).show();
						currPos.prevCell.attr("rowspan",currPos.index);
					});
				}
				// 计算新增行的top
				var tempTop = setting.posTr.position().top - newTrDom.height(),
					bodyPanel = grid.getBodyPanel();
				top = (tempTop < 0 || tempTop > bodyPanel.height()) ? tempTop : bodyPanel.scrollTop();
			} else {
				tbody.append(newTrDom);
			}
			if (op._fnEndInsertRow) {
				op._fnEndInsertRow.call(grid, newTrDom, setting, record.data);
			}
			// 新增一行后，调用行渲染事件
			op.fnRenderRow && op.fnRenderRow.call(grid, newTrDom, record.data, record.data.rowIdx);
			// 是否显示编辑器
			if (op.showFirstEditor && isAppendRow !== true && newTrDom.position().top >= -1) {
				newTrDom.find(".grid-cell").each(function (i, tdDom) {
					var td = $(tdDom);
					if (td.attr("eno") == "edit") {
						if (grid.callEditor(td) !== false) {
							return false;
						}
					}
				});
			}
			// 存在编辑器时，修正编辑器的位置
			IGrid.Editor.activeEditor(grid);
			//是否滚动到新增数据的位置
			setting.scroll && this.scroll(grid,top);
			grid.totalColumn();
			return top;
		},
		//复制新增
		copy: function (grid, op, optOp,setting)
		{
			var top, isScroll = setting.scroll,copied,
				insertPos = setting.posTr ? true : null;
			if(op._cache)
			{//根据缓存的数据进行
				var records = grid.getSelectedRecords(), tr;
				if(records.length)
				{
					copied = true;
					setting.scroll = null;
					$.each(records,function(i,record){
						tr = grid.getRow(record.rowIdx);
						grid.op.Storage.setItemSelected(record, false, tr);
						top = gridInsert.copyInsert(grid,op,record,optOp,setting,top,insertPos);
					});
				}
			}
			else 
			{//根据选择的列进行复制新增
				var rows = grid.getSelectRows(),
					selectedHead;
				if (rows.length)
				{
					copied = true;
					// 获取选中行的表头
					selectedHead = grid.getHeadTable().find("." + Const.selected.css);
					// 存在将选中样式去掉
					(selectedHead.length > 0) && selectedHead.removeClass(Const.selected.css, false);
					setting.scroll = null;
					rows.each(function (i){
						var tr = $(this),record = grid.getRowData(tr);
						grid.op.Storage.setItemSelected(record,false,tr);
						top = gridInsert.copyInsert(grid,op,record,optOp,setting,top,insertPos);
					});
				}
			}
			if(top != null)
				isScroll && this.scroll(grid,top);
			else
				copied || this.insertDefault(grid,op,optOp,setting);
				//gridInsert.insert(grid, op, optOp.defaultRow,setting);
		},
		insertDefault:function(grid,op,optOp,setting){
			this.insert(grid,op,$.extend(true, {}, optOp.defaultRow),setting);
		},
		copyInsert:function(grid,op,record,optOp,setting,top,insertPos){
			var data = $.extend(true,{},record);
			//初始化数据默认值
			gridInsert.clearField(op,data, optOp);
			var trTop = gridInsert.insert(grid, op, {data:data},setting);
			//insertPos && setting.posTr && (setting.posTr = setting.posTr.next());
			return top ? top : trTop;
		},
		scroll:function(grid,top){
			var panel = grid.getBodyPanel(),
				scropTop = panel.scrollTop();
			(top < scropTop || top > scropTop + panel.height() - 30) && grid.syncScroll(null, top);
		},
		//初始化默认值
		clearField: function (op,data, optOp)
		{
			if (optOp.clear)
			{
				$.each(optOp.clear, function (i, field){
					data[field] = optOp.defaultRow.data[field];
				});
			}
			delete data._index;
			op.Storage.clearStatus(data);
		}
//		,clear:function(grid){
//			grid.getDataBody().prev().empty();
//		}
	};
	
	/** 注册新增操作 */
	IGrid.Operation.add("insert", {
		bind: function (grid, op, optOp)
		{
			this.base.bind.call(this, grid, op, optOp);
			var data = optOp.defaultRow,helper = Ccay.DataHelper;
			data || (data = {});
			//初始化默认数据
			$.each(op.columns, function (i, col)
			{
				if(!col.inner && !col.columnType)
				{
					helper.getObj(col.field, data) == undefined && helper.setObj(col.field, data, null);
					col.valueField && helper.getObj(col.valueField, data) == undefined && helper.setObj(col.valueField, data, null);
				}
			});
			optOp.defaultRow = {data:data};
			optOp.index = 0;
			//初始化新增数据仓库
			gridInsert.initInsertStorage(grid.op.Storage,grid.op,grid);
		},
		operate: function (grid, op, optOp)
		{
			var setting = optOp._getInsertSet ? optOp._getInsertSet(grid,op) : {};
			setting.scroll !== false && (setting.scroll = true);
			optOp.copy ? gridInsert.copy(grid, op, optOp,setting) : 
				gridInsert.insertDefault(grid, op,optOp,setting);
		}
	});
	
	var gridSave = IGrid.Operation.save = {
		checkErrorMsg: function (grid, errorMsg) {
			//错误数据
   			var errorRecords = {}, errorNo, tempLen, tempIdx, tempData, errorRecord;
   			for (var i=0, fieldError; fieldError = errorMsg[i]; i++) {
   				var fieldName = fieldError.fieldName.split(".").pop(),
					rowIndex = fieldError.rowIndex;
				// 判断是否是同一行数据，若不是同一行，则将上一行的错误数据放入错误集中，然后，设置当前行的错误信息
				if (tempIdx != rowIndex) {
					if (errorRecord && errorNo) {
						errorRecord.lenght = tempLen;
						errorRecords[errorNo] = errorRecord;
					}
					// 计算一条数据的错误个数
					tempLen = 0;
					errorNo = $.newGuid();
					errorRecord = {};
					tempIdx = rowIndex;
					// 获取错误数据
					tempData = grid.getRowData(rowIndex);
					// 给错误数据添加标示
					tempData._errorNo = errorNo;
				}
				errorRecord[fieldName] = fieldError.messages;
				tempLen++;
   			}
   			// 循环到最后一次时，将错误数据放到错误集中
   			errorRecord.lenght = tempLen;
   			errorRecords[errorNo] = errorRecord;
   			grid.op._errorMsg = errorRecords;
		}
	};
	
	/** 注册保存操作 */
	IGrid.Operation.add("save", {
		bind: function (grid, op, optOp)
		{
			if (optOp.btn)
			{
				var operate = this.operate;
				$(optOp.btn).unbind("click").click(function (e)
				{
					e.stopPropagation();
					if(!op._disabled){
						// 前台验证通后后才进行后台操作 l00195395
						if(grid.valid() && !grid.getDataBody().find(".igrid-servervalid-error").length){
							operate(grid, op, optOp)
						}else{
							// 开启showStatus后前台验证弹出 
							if(grid.op.showStatus && grid.setErrorMsg(grid.getInsertedRecords())){
				       			// 更新错误状态
								grid.updateStatus("error");
								// 弹出
								if(grid.op.popupStatus){
				       				grid.popupStatus("error");
				       			}
							}
						}
					}
				});
			}
		},
		operate: function (grid, op, optOp)
		{
			var storage = op.Storage, data;
			// 保存前，将所有数据的errorNo给清除掉
			if (op._errorMsg) {
				op._errorMsg = null;
				storage.filter(function (item) {
					item._errorNo && (item._errorNo = null);
				});
			}
			data = storage.getChangedRecords();
			// 若存在有效数据，则发送请求；否则，删除无效数据
			if (data.insertedRecords.length || data.updatedRecords.length || data.deletedRecords.length)
			{
				var ajax = $.extend(true, {}, optOp.ajax);
				ajax.data = {
					items2Delete: data.deletedRecords,
					items2Create: data.insertedRecords,
					items2Update: data.updatedRecords
				};
				// 保存前的干预方法
				if (!optOp.fnBeforeSave || optOp.fnBeforeSave(ajax.data, ajax, grid, optOp) !== false) {
					grid.save(ajax, true);
				}
			} else {
				var preDeletedRecords = storage.getPreDeletedRecords(), isHasNew;
				// 获取删除的新增数据
				if (preDeletedRecords.length) {
					// 遍历删除的新增数据
					$.each(preDeletedRecords, function (i, item) {
						// 删除新增数据
						if (GridDelete.delInsertRow(grid, storage, item)) {
							// 标识数据集中有新增数据
							isHasNew = true;
						}
					});
					op._loadType = "noScroll";
					// 若删除的是数据集中的数据，则需要重新加载
					if (isHasNew) {
						storage.destroy(function(item){
							return item ? item._destroy : this.ReturnValue.complete;
						});
						grid.reload();
					}
				} else {
					Ccay.UI.topBox("ccay.common.message.nothingModified");
				}
			}
		}
	});
	
})(Ccay.UI.IGrid,Ccay.UI.IGrid.Const);